package com.sanglh.tutorial.asynctask;

import java.util.ArrayList;

import android.app.ListActivity;
import android.app.LoaderManager.LoaderCallbacks;
import android.content.AsyncTaskLoader;
import android.content.Context;
import android.content.Loader;
import android.content.pm.ApplicationInfo;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ListView;

import com.sanglh.tutorial.R;
import com.sanglh.tutorial.common.util.AppUtils;
import com.sanglh.tutorial.common.util.CollectionUtils;

public class AsyncActivity extends ListActivity implements
		LoaderCallbacks<ArrayList<AsyncEntry>>, OnItemClickListener{
	private ArrayList<AsyncEntry> entries;
	private AsyncAdapter<AsyncEntry> adapter;
	private ListView listView;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_async_task);
		listView = getListView();
		entries = new ArrayList<>();
		adapter = new AsyncAdapter<>(this, entries, R.layout.row_async_app);
		listView.setAdapter(adapter);
		listView.setOnItemClickListener(this);
		getLoaderManager().initLoader(0, null, this).forceLoad();
		;
	}

	public static class AsyncLoader extends
			AsyncTaskLoader<ArrayList<AsyncEntry>> {
		private Context context;
		private ArrayList<AsyncEntry> mApps;

		public AsyncLoader(Context context) {
			super(context);
			this.context = context;
		}

		@Override
		public ArrayList<AsyncEntry> loadInBackground() {
			ArrayList<ApplicationInfo> apps = AppUtils
					.getAllKnownApplication(context);
			ArrayList<AsyncEntry> entries = new ArrayList<>();
			for (ApplicationInfo app : apps) {
				entries.add(new AsyncEntry(AppUtils.getApplicationIcon(context,
						app), AppUtils.getApplicationLabel(context, app), app.packageName));
			}
			return entries;
		}

		/**
		 * Called when there is new data to deliver to the client. The super
		 * class will take care of delivering it; the implementation here just
		 * adds a little more logic.
		 */
		@Override
		public void deliverResult(ArrayList<AsyncEntry> apps) {
			if (isReset()) {
				// An async query came in while the loader is stopped. We
				// don't need the result.
				if (apps != null) {
					onReleaseResources(apps);
				}
			}
			ArrayList<AsyncEntry> oldApps = mApps;
			mApps = apps;

			if (isStarted()) {
				// If the Loader is currently started, we can immediately
				// deliver its results.
				super.deliverResult(apps);
			}

			// At this point we can release the resources associated with
			// 'oldApps' if needed; now that the new result is delivered we
			// know that it is no longer in use.
			if (oldApps != null) {
				onReleaseResources(oldApps);
			}
		}

		/**
		 * Handles a request to start the Loader.
		 */
		@Override
		protected void onStartLoading() {
			if (mApps != null) {
				// If we currently have a result available, deliver it
				// immediately.
				deliverResult(mApps);
			}

			// Start watching for changes in the app data.
			// if (mPackageObserver == null) {
			// mPackageObserver = new PackageIntentReceiver(this);
			// }

			// Has something interesting in the configuration changed since we
			// last built the app list?
			// boolean configChange = mLastConfig.applyNewConfig(getContext()
			// .getResources());

			// if (takeContentChanged() || mApps == null || configChange) {
			// // If the data has changed since the last time it was loaded
			// // or is not currently available, start a load.
			// forceLoad();
			// }
			if (takeContentChanged() || mApps == null) {
				// If the data has changed since the last time it was loaded
				// or is not currently available, start a load.
				forceLoad();
			}
		}

		/**
		 * Handles a request to stop the Loader.
		 */
		@Override
		protected void onStopLoading() {
			// Attempt to cancel the current load task if possible.
			cancelLoad();
		}

		/**
		 * Handles a request to cancel a load.
		 */
		@Override
		public void onCanceled(ArrayList<AsyncEntry> apps) {
			super.onCanceled(apps);
			// At this point we can release the resources associated with 'apps'
			// if needed.
			onReleaseResources(apps);
		}

		/**
		 * Handles a request to completely reset the Loader.
		 */
		@Override
		protected void onReset() {
			super.onReset();

			// Ensure the loader is stopped
			onStopLoading();

			// At this point we can release the resources associated with 'apps'
			// if needed.
			if (mApps != null) {
				onReleaseResources(mApps);
				mApps = null;
			}

			// Stop monitoring for changes.
			// if (mPackageObserver != null) {
			// getContext().unregisterReceiver(mPackageObserver);
			// mPackageObserver = null;
			// }
		}

		/**
		 * Helper function to take care of releasing resources associated with
		 * an actively loaded data set.
		 */
		protected void onReleaseResources(ArrayList<AsyncEntry> apps) {
			// For a simple List<> there is nothing to do. For something
			// like a Cursor, we would close it here.
		}

	}

	@Override
	public Loader<ArrayList<AsyncEntry>> onCreateLoader(int id, Bundle args) {
		return new AsyncLoader(AsyncActivity.this);
	}

	@Override
	public void onLoadFinished(Loader<ArrayList<AsyncEntry>> loader,
			ArrayList<AsyncEntry> data) {
		entries.addAll(data);
		CollectionUtils.sort(entries, "name");
		adapter.notifyDataSetChanged();

	}

	@Override
	public void onLoaderReset(Loader<ArrayList<AsyncEntry>> loader) {
		// TODO Auto-generated method stub

	}

	@Override
	public void onItemClick(AdapterView<?> parent, View view, int position,
			long id) {
//		AppUtils.uninstallApp(AsyncActivity.this, entries.get(position).pkg);
		
	}

}
